package com.share.tool.generator.db_bak;

import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.share.common.utils.DateUtil;
import com.share.common.utils.DbUtil;
import com.share.common.utils.EnvUtil;
import com.share.tool.generator.db_bak.config.BakConfig;
import com.share.tool.generator.db_bak.enums.DbEnum;
import com.share.tool.generator.db_bak.model.ShowCreateTable;
import com.share.tool.generator.db_bak.model.ShowTables;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 01401061 - 孙艳强
 * @date 2020/10/29 21:58
 */
@Slf4j
public class MainDbBak {
    public static void main(String[] args) throws Exception {
//        DbEnum[] values = {DbEnum.NACOS, DbEnum.SHARE, DbEnum.SHARE_ADMIN};
//        DbEnum[] values = {DbEnum.SHARE, DbEnum.NACOS, DbEnum.MOCK, DbEnum.FINANCE, DbEnum.SELENIUM};
        DbEnum[] values = {DbEnum.ADMIN};
        for (DbEnum db : values) {
            Connection con = DbUtil.getConnection(db.getDriver(), db.getUrl(), db.getUser(), db.getPassword());
            String dbName = DbUtil.getDbName(con);
            List<ShowTables> tables = showTables(con);
            bakTables(con, tables);
            bakTablesData(con, tables, BakConfig.getList(dbName));
            con.close();
        }
    }

    private static String bakTablesData(Connection con, List<ShowTables> tables, List<String> bakList) {
        if (tables == null || tables.isEmpty() || bakList == null) {
            return null;
        }

        //赛选出,存在需要定义列的table
        List<String> columnTableList = bakList.stream().map(e -> e.trim()).filter(e -> e.contains(" ") || e.contains(",")).collect(Collectors.toList());
        String dbName = DbUtil.getDbName(con);
        StringBuffer sbTmp = new StringBuffer();
        try {
            for (ShowTables table : tables) {
                String sql = null;
                String tableName = table.getTables_in_();
                if (bakList.contains(tableName)) {
                    sql = "select * from " + tableName;
                } else {
                    for (String columnTable : columnTableList) {
                        if (columnTable.endsWith(tableName)) {
                            StringBuffer stmp = new StringBuffer();
                            stmp.append(columnTable);
                            stmp.insert(columnTable.lastIndexOf(tableName) - 1, " from "); //插入from
                            stmp.insert(0, "select ");
                            sql = stmp.toString();
                            break;
                        }
                    }
                }

                //执行sql
                if (StringUtils.isNotBlank(sql)) {
                    PreparedStatement ps = con.prepareStatement(sql);
                    ResultSet rs = ps.executeQuery();
                    List<String> tableDataList = DbUtil.convertSelectToInsert(table.getTables_in_(), rs);
                    for (String str : tableDataList) {
                        sbTmp.append(str);
                    }
                    if (!tableDataList.isEmpty()) {
                        sbTmp.append(System.lineSeparator());
                    }
                }
            }
            String dbBakdir = EnvUtil.USER_DIR + File.separator + "doc" + File.separator + "db";
            String fileName = dbBakdir + File.separator + dbName + "-data-" + DateUtil.getDate() + ".sql";
            Files.asCharSink(new File(fileName), Charsets.UTF_8).write(sbTmp.toString());
            log.info(dbName + "数据备份完毕,path=" + fileName);
            return fileName;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("数据备份失败!!!");
            return null;
        }
    }

    private static String bakTables(Connection con, List<ShowTables> tables) {
        if (tables == null || tables.isEmpty()) {
            return null;
        }

        int count = 0;
        String dbName = DbUtil.getDbName(con);
        StringBuffer sbTmp = new StringBuffer();

        try {
            for (ShowTables table : tables) {
                PreparedStatement ps = con.prepareStatement("show  create table " + table.getTables_in_());
                ResultSet rs = ps.executeQuery();
                List<ShowCreateTable> showCreateTables = DbUtil.convertBean(rs, ShowCreateTable.class);
                if (showCreateTables == null || showCreateTables.size() > 1) {
                    continue;
                }

                count++;
                sbTmp.append(showCreateTables.get(0).getCreateTable() + ";");
                sbTmp.append(System.lineSeparator());
                sbTmp.append(System.lineSeparator());
                log.info(count + "\t正在处理表-" + table.getTables_in_());
            }
            String dbBakdir = EnvUtil.USER_DIR + File.separator + "doc" + File.separator + "db";
            String fileName = dbBakdir + File.separator + dbName + "-structure-" + DateUtil.getDate() + ".sql";
            Files.asCharSink(new File(fileName), Charsets.UTF_8).write(sbTmp.toString());
            log.info(dbName + "表结构备份完毕,path=" + fileName);
            return fileName;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("表结构备份失败!!!");
            return null;
        }
    }

    private static List<ShowTables> showTables(Connection con) {
        try {
            //3、获取发送SQL语句的对象
            PreparedStatement ps = con.prepareStatement("show  tables");

            //4、发送SQL语句，返回结果集
            ResultSet rs = ps.executeQuery();
            return DbUtil.convertBean(rs, ShowTables.class);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
}
